﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace Pahan.McuFusion.Common.Serialization
{
    /// <summary>
    /// Base class for reading the lists of <see cref="DeviceInfo"/>.
    /// </summary>
    /// <typeparam name="TDeviceInfo">The type of device info.</typeparam>
    public abstract class DeviceInfoListReader<TDeviceInfo> : IDeviceInfoListReader<TDeviceInfo>
        where TDeviceInfo : DeviceInfo
    {
        /// <summary>
        /// Read the list from file.
        /// </summary>
        public IEnumerable<TDeviceInfo> ReadList(string filename)
        {
            using (var input = File.OpenRead(filename))
            {
                return ReadList(input);
            }
        }

        /// <summary>
        /// Reads the list from stream.
        /// </summary>
        public IEnumerable<TDeviceInfo> ReadList(Stream input)
        {
            Type surrogateType = GetSurrogateType();
            if (surrogateType != null)
            {
                return DoReadList(input, surrogateType)
                    .Cast<IBuilder<TDeviceInfo>>()
                    .Select(surrogate => surrogate.Build());
            }
            else
            {
                return DoReadList(input, typeof(TDeviceInfo)).Cast<TDeviceInfo>();
            }
        }

        /// <summary>
        /// Performs actual reading from stream.
        /// </summary>
        protected abstract IEnumerable DoReadList(Stream input, Type type);

        private Type GetSurrogateType()
        {
            var surrogateAttribute = typeof(TDeviceInfo).GetCustomAttributes(
                typeof(DeviceInfoSurrogateAttribute), false)
                .Cast<DeviceInfoSurrogateAttribute>().FirstOrDefault();
            return surrogateAttribute != null ? surrogateAttribute.SurrogateType : null;
        }
    }
}
